﻿/***********************************************************************************************
 * 
 * ProjectName: WMSSoft.Lib.WinKStart
 * 
 * Description: Class to read RecentOpenedDocument from Disk
 * 
 * Created:     21.07.2012
 * 
 * Author:      matthias wagler - matthias@WMSSoft.de
 * 
 * Copyright:   Copyright 2012 by WMSSoft.net
 * 
 * License:     GPLv3
 * 
 * History:     21.07.2012 - matthias wagler matthias@WMSSoft.de   -   Created
 * 
 **********************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.ComponentModel;
using WMSSoft.Lib.Basic;
using WMSSoft.Lib.Enums;
using WMSSoft.Lib.WinKStart;
using WMSSoft.Lib.Interfaces;

namespace WMSSoft.WinKStart.DataSource.Recent
{
    public class cRecentReader
    {
        Dictionary<string, object> _RecentDocumentItems = null;
        cStartmenuItem _RootRecentDocumentMenuItem = null;
        cStartmenuItem _Thread_RecentDocuments_Root = null;
        DispatcherTimer m_DataLoadState = null;
        BackgroundWorker m_BackgroundWorker = null;
        System.IO.FileSystemWatcher m_FileSystemWatcher = null;
        string m_RecentPath = "";

        Dictionary<string, KeyValueAssignment> _Extension = null;
        Dictionary<string, KeyValueAssignment> m_Options = null;
        bool _StopThreadWork = false;
        long m_LastUpdate = 0;

        public event EventHandler UpdateMenuItems;

        public cRecentReader()
        {
            //init dictionary
            _RecentDocumentItems = new Dictionary<string, object>();
            _RootRecentDocumentMenuItem = new cStartmenuItem("root", "RecentOpenedDocuments", eLinkExecutionTypes.Program, "", eExecutionProcedure.Unknown,
                                                    eItemType.Root, "", null, null, "", "","","");

            m_RecentPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Recent);

            m_FileSystemWatcher = new System.IO.FileSystemWatcher(m_RecentPath, "*.lnk");
            m_FileSystemWatcher.EnableRaisingEvents = true;
            m_FileSystemWatcher.Created += m_FileSystemWatcher_Activate;
            m_FileSystemWatcher.Changed += m_FileSystemWatcher_Activate;
            m_FileSystemWatcher.Deleted += m_FileSystemWatcher_Activate;
            //AddCategoriesToParent(_RootRecentDocumentMenuItem);
            //LoadRecentDocuments();
            //LoadRecentOpenedDocuments();
        }

        public bool StopWorking()
        {
            _StopThreadWork = true;
            m_BackgroundWorker.CancelAsync();
            return true;
        }

        public Dictionary<string, KeyValueAssignment> Extension
        {
            get { return _Extension; }
            set { _Extension = value; }
        }

        public Dictionary<string, KeyValueAssignment> Options
        {
            get { return m_Options; }
            set { m_Options = value; }
        }

        public cStartmenuItem RootMenuItem
        {
            get
            {
                return _RootRecentDocumentMenuItem;
            }
        }

        public cStartmenuItem LoadRecentDocuments()
        {
            try
            {
                _Thread_RecentDocuments_Root = _RootRecentDocumentMenuItem;

                m_BackgroundWorker = new BackgroundWorker();
                m_BackgroundWorker.WorkerReportsProgress = true;
                m_BackgroundWorker.WorkerSupportsCancellation = true;
                m_BackgroundWorker.ProgressChanged += worker_ProgressChanged;
                m_BackgroundWorker.DoWork += m_BackgroundWorker_DoWork;

                m_DataLoadState = new DispatcherTimer(DispatcherPriority.Normal);
                m_DataLoadState.Interval = new TimeSpan(0,0,1);
                m_DataLoadState.Tick += m_DataLoadState_Tick;

                m_DataLoadState.Start();

                //_StartMenuReader_Thread = new Thread(ThreadMethode_LoadRecentDocuments);
                //_StartMenuReader_Thread.Start();

                return _RootRecentDocumentMenuItem;
            }
            catch (Exception Ex)
            {
                CMessagelogging.AppendMessage("Unable to load Recent Documents!", Ex, EMessageTypes.Error);
                return null;
            }
        }
        void m_FileSystemWatcher_Activate(object sender, System.IO.FileSystemEventArgs e)
        {
            m_LastUpdate = 0;
            if (m_DataLoadState.IsEnabled == false) m_DataLoadState.Start();
            //LoadFromDisk();
        }

        void m_DataLoadState_Tick(object sender, EventArgs e)
        {            
            if (m_BackgroundWorker.IsBusy == false && m_LastUpdate == 0)
            {
                m_DataLoadState.Stop();
                m_BackgroundWorker.RunWorkerAsync();                
            }
        }

        void m_BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            ThreadMethode_LoadRecentDocuments();
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            m_LastUpdate = DateTime.Now.Ticks;
            _RootRecentDocumentMenuItem = (cStartmenuItem)e.UserState;

            if (UpdateMenuItems != null) UpdateMenuItems(null, EventArgs.Empty);
        }

        private void ThreadMethode_LoadRecentDocuments()
        {
            try
            {
                _Thread_RecentDocuments_Root.Clear();
                //first, apply all filter items
                ApplyFileExtensions();
                //implements code to read the windows opened files
                //string sRecentOpenedDocumentsBasicPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Recent);
                _RootRecentDocumentMenuItem.ContentType = eContentPanelContentType.RecentOpenedDocuments;
                SearchItemsRecursiv(m_RecentPath, _Thread_RecentDocuments_Root);

                
            }
            catch (Exception Ex)
            {
                //write error to Messagebus
                CMessagelogging.AppendMessage("Error while loading recent opened Documents from disk!", Ex, EMessageTypes.Error);               
            }
            finally
            {
                //_RootRecentDocumentMenuItem = _Thread_RecentDocuments_Root;
                m_BackgroundWorker.ReportProgress(100, _Thread_RecentDocuments_Root);
                //if (UpdateMenuItems != null) UpdateMenuItems(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// The Methode read all Files an directories (with all Subdirectories) from his given path
        /// </summary>
        /// <param name="Startfolder">Path to search from</param>
        /// <param name="Parent">Parent to add childs</param>
        private void SearchItemsRecursiv(string Startfolder, cStartmenuItem Parent)
        {
            try
            {
                string[] DirFiles = System.IO.Directory.GetFiles(Startfolder);
                System.Windows.Media.Imaging.BitmapImage myBImg = null;// basic_GraphicHelpers.WPFBitmapFromDrawingImage(WMSSoft.Lib.WinKStart.Properties.Resources.Executable);
                cStartmenuItem myStartmenuItem = null;
                string CategoryName = "";

                foreach (string File in DirFiles)
                {
                    //check we want to stop threads work
                    if (_StopThreadWork == true) break;

                    if (Parent != null)
                    {
                        //if used has stopped the app we do exit this function here
                        if (m_BackgroundWorker.CancellationPending == true) return;

                        myStartmenuItem = cStartmenuItem.MakeInstance(File, Parent, false );
                        
                        CategoryName = "";

                        if (myStartmenuItem != null)
                        {
                            myStartmenuItem.ContentType = eContentPanelContentType.RecentOpenedDocuments;

                            if (_Extension != null)
                            {
                                if (myStartmenuItem.ItemType == eItemType.Link)
                                {
                                    string smyFileExt = System.IO.Path.GetExtension(myStartmenuItem.LinkFilename).ToUpper();
                                    smyFileExt = smyFileExt.Replace(".", "");
                                    if (_Extension.ContainsKey(smyFileExt.ToUpper()) == true)
                                    {
                                        myStartmenuItem.Filter = _Extension[smyFileExt.ToUpper()].Value;

                                        //add this Item as child to parent item
                                        if (Parent.ChildItems.ContainsKey(myStartmenuItem.Filter.ToUpper()))
                                            ((cStartmenuItem)Parent.ChildItems[myStartmenuItem.Filter.ToUpper()]).AddChild(myStartmenuItem);
                                        else
                                            Parent.AddChild(myStartmenuItem);
                                    }
                                    else
                                    {
                                        //add this Item as child to parent item
                                        Parent.AddChild(myStartmenuItem);
                                    }
                                }
                            }
                            else
                            {
                                //add this Item as child to parent item
                                Parent.AddChild(myStartmenuItem);
                            }
                        }
                    }
                }                

            }
            catch (Exception Ex)
            {
                CMessagelogging.AppendMessage("Error while reading startmenuitems!", Ex, EMessageTypes.Error);
            }
        }

        void ApplyFileExtensions()
        {
            try
            {
                if (_Extension != null && _Extension.Count > 0)
                {
                    Dictionary<string, KeyValueAssignment>.KeyCollection tmpKeys = _Extension.Keys;
                    foreach (string Item in tmpKeys)
                    {
                        if (_Thread_RecentDocuments_Root.ChildItems.ContainsKey(_Extension[Item].Value) == false)
                        {
                            cStartmenuItem tmpFilterItem = (cStartmenuItem)CreateFilterNode(_Extension[Item].Value);

                            _Thread_RecentDocuments_Root.AddChild(tmpFilterItem);
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                throw new Exception("Can't apply FilExtensionToFilter!", Ex);
            }
        }

        iWinKStartItem CreateFilterNode(string FilterName)
        {
            try
            {
                return new cStartmenuItem(FilterName.ToUpper(), FilterName, eLinkExecutionTypes.Program, "", eExecutionProcedure.Unknown,
                                          eItemType.Filter, "", null, null, "", "", "", "");
            }
            catch (Exception Ex)
            {
                throw new Exception("Can't create Filter!", Ex);
            }
        }
    }
}
